﻿using System;
using System.Collections.Generic;
using System.Configuration;
using System.Globalization;
using System.Linq;
using System.Text;
using System.Web.UI.WebControls;
using Medianamik.Core;
using Medianamik.Core.Configuration;
using Medianamik.Core.Security;
using Medianamik.Core.Sugar;
using Medianamik.Core.Urls;
using Medianamik.Globalization;
using Medianamik.UI.Controls;
using Telerik.Web.UI;

namespace Medianamik.UI.ContentManagement
{
    public partial class RevisionManagement : BasePage
    {
        private Guid _nodeID;  //Param obligatoire

        readonly static MedianamikConfigSection Config = (MedianamikConfigSection)ConfigurationManager
            .GetSection(ConfigurationSectionName.MEDIANAMIK);

        readonly BaseModalWindow _propertyPreviewWindow = new BaseModalWindow();

        protected void Page_Load(object sender, EventArgs e)
        {
            //Param obligatoire

            if (!StringHelper.IsGuid(Request.QueryString[DefaultParamNames.NodeID], out _nodeID) ||
                CurrentNode == null)
            {
                Response.Redirect(ReturnURL);
            }


            if (!IsPostBack)
            {
                if (CurrentNode == null || CurrentNode.DefaultInstance == null)
                    Response.Redirect(ReturnURL);
                else
                {
                    if (!Roles.IsUserInRole(MedianamikRoles.ManageContent) ||
                     !Roles.UserHasRight(CurrentNode, SecurityLevels.Update))
                        Response.Redirect("/medianamik/Unauthorized.aspx");

                    RevisionLockActivator.ObjectId = CurrentNode.ID;
                    RevisionLockActivator.OnClientUltimatumReached = "function(){window.focus();alert('" +
                        Translator.TranslateJS("Medianamik_LockManagement", "UltimatumReached") +
                        "'); location.replace('" + ReturnURL + "');}";

                    _propertyPreviewWindow.IconUrl = "/Medianamik/images/Icones/Ico_Visualisation.gif";
                    _propertyPreviewWindow.ReloadOnShow = true;
                    _propertyPreviewWindow.Width = Unit.Pixel(640);
                    _propertyPreviewWindow.Height = Unit.Pixel(480);
                    LoadBreadCrumbs();
                }
            }
        }

        protected void Page_Init(object sender, EventArgs e)
        {
            _propertyPreviewWindow.ID = "PropertyPreviewWindow";
            MyWindowManager.Windows.Add(_propertyPreviewWindow);
        }

        protected void RevisionDataBound(object sender, GridItemEventArgs e)
        {
            if (e.Item.ItemType == GridItemType.Item || e.Item.ItemType == GridItemType.AlternatingItem)
            {
                var gridItem = (GridDataItem)e.Item;

                if (gridItem.DataItem != null)
                {
                    var publication = gridItem.DataItem as Publication;
                    if (publication != null)
                    {
                        var revisionRadioButton = (RadioButton)e.Item.FindControl("RevisionRadioButton");
                        revisionRadioButton.Text = ToPublicationName(publication.StartDate, e.Item.ItemIndex);
                    }
                }
            }
        }

        private string ToPublicationName(DateTime publicationDate, int index)
        {
            return Translator.Translate("Medianamik_ContentManagement", "PublicationOf") + 
                publicationDate.ToString("F", CurrentUICulture) +
                   (index == 0 ? " (publication actuelle)" : "");
        }

        protected void LoadRevisions(object source, GridNeedDataSourceEventArgs e)
        {
            RevisionGrid.DataSource = CurrentNode.DefaultInstance.NewPublications;
        }

        protected void SelectedRevisionChanged(object sender, EventArgs e)
        {
            var clickedItem = (sender as RadioButton).NamingContainer as GridDataItem;
            int index = clickedItem.ItemIndex;

            foreach (GridItem item in RevisionGrid.MasterTableView.Items)
            {
                if (item.ItemIndex != index && item is GridDataItem)
                {
                    var nonActive = item as GridDataItem;
                    (nonActive.FindControl("RevisionRadioButton") as RadioButton).Checked = false;
                }
            }

            var revison = (DateTime)clickedItem.OwnerTableView.DataKeyValues[clickedItem.ItemIndex]["StartDate"];

            RevisionDetail.Text = BuildRevisionDetailTable(CurrentNode.DefaultInstance
                .GetPropertiesForRevision(revison), revison, index);
        }

        protected void LockLink_RequestFailed(object sender, CommandEventArgs e)
        {
            LockInfoTooltip.ObjectId = new Guid((string)e.CommandArgument);
            LockInfoTooltip.DataBind();
            LockInfoTooltip.Show();
        }

        Node _currentNode;
        Node CurrentNode
        {
            get
            {
                if (_currentNode == null)
                {
                    _currentNode = NodeManager.GetNode(_nodeID);
                    _currentNode.DefaultCulture = MedianamikContext.Current.EditionCulture;
                }

                return _currentNode;
            }
        }

        protected string ReturnURL
        {
            get
            {
                if (string.IsNullOrEmpty(Request.QueryString[DefaultParamNames.ReturnURL]))
                {
                    //par defaut on retourne à NodeList 
                    var returnURL = "NodeList.aspx";

                    if (CurrentNode.ParentID.HasValue)
                        returnURL += "?" + DefaultParamNames.ParentNodeID + "=" + CurrentNode.ParentID.Value;
                    return returnURL;
                }

                return Request.QueryString[DefaultParamNames.ReturnURL].UrlDecodeBase64();
            }
        }

        private string BuildRevisionDetailTable(IEnumerable<NodeProperty> properties,
            DateTime publicationDate, int index)
        {
            var modifiedPropertiesGroupedByGroupName = properties
                .Select(p => new PropertyPair(CurrentNode
                    .DefaultInstance.Properties[p.NodeTypePropertyID],
                    p, CurrentNode.DefaultCulture)).Where(pp => pp.hasChanged).GroupBy(pp => pp.GroupName);

            var revisionDetailTableBuilder = new StringBuilder();

            var revisionName = ToPublicationName(publicationDate, index);

            revisionDetailTableBuilder.AppendLine("<h2>" + Translator.Translate("Medianamik_ContentManagement", "DraftComparison") + revisionName + "</h2>");

            if (modifiedPropertiesGroupedByGroupName.Count() > 0)
            {
                saveButton.Enabled = true;

                if (index == 0)
                    saveButton.NavigateUrl = "javascript:void(radalert('" + Translator.Translate("Medianamik_ContentManagement", "RevertInsteadMessage") + "'));";
                else
                    saveButton.NavigateUrl = "Nodemanagement.aspx?" + DefaultParamNames.NodeID + "=" + CurrentNode.ID +
                        "&revision=" + publicationDate.Ticks;


                saveButton.CssClass = "Action BtRevision";


                revisionDetailTableBuilder.AppendLine("<table class=\"TableauRevision\" cellspacing=\"0\" cellpadding=\"0\" border=\"0\">");
                revisionDetailTableBuilder.AppendLine("<tr>");
                revisionDetailTableBuilder.AppendFormat("<th colspan=\"2\" width=\"48%\">{0}</th>\n",
                    revisionName);
                revisionDetailTableBuilder.AppendLine("<th class=\"CellVide\" width=\"6%\">&nbsp;</th>");
                revisionDetailTableBuilder.AppendFormat("<th colspan=\"2\" width=\"48%\">{0}</th>\n",
                    Translator.Translate("Medianamik_ContentManagement", "DraftVersion"));
                revisionDetailTableBuilder.AppendLine("</tr>");


                foreach (var group in modifiedPropertiesGroupedByGroupName)
                {
                    if (group.Count() > 0)
                    {

                        revisionDetailTableBuilder.AppendLine("<tr>");
                        revisionDetailTableBuilder.AppendFormat("<td class=\"CellOnglet\" colspan=\"2\">{0}</td>\n",
                            Translator.Translate(ResourceSets.Tabs, group.Key));
                        revisionDetailTableBuilder.AppendLine("<td class=\"CellVide\" width=\"6%\">&nbsp;</td>");
                        revisionDetailTableBuilder.AppendFormat("<td class=\"CellOnglet\" colspan=\"2\">{0}</td>\n",
                                        Translator.Translate(ResourceSets.Tabs, group.Key));
                        revisionDetailTableBuilder.AppendLine("</tr>");



                        revisionDetailTableBuilder.AppendFormat(@"<tr>
					        <td width=""18%"" class=""CellNomChamp""><strong>{0}</strong></td>
					        <td width=""30%"" class=""CellNomChamp""><strong>{1}</strong></td>
					        <td class=""CellVide"" width=""6%"">&nbsp;</td>
					        <td width=""18%"" class=""CellNomChamp""><strong>{0}</strong></td>
					        <td width=""30%"" class=""CellNomChamp""><strong>{1}</strong></td>
				        </tr>", Translator.Translate("Medianamik_ContentManagement", "Field"),
                              Translator.Translate("Medianamik_ContentManagement", "Data"));



                        foreach (var propertyPair in group.OrderBy(p => p.Position))
                        {
                            var fieldNameColumn = String.Format("<td>{0}</td>\n",
                                propertyPair.TranslatedName);
                            revisionDetailTableBuilder.AppendLine("<tr>");
                            revisionDetailTableBuilder.AppendFormat(fieldNameColumn);
                            revisionDetailTableBuilder.AppendFormat("<td>{0}</td>\n",
                                                                    FormatProperty(propertyPair,
                                                                                         PropertyVersion.Previous));
                            revisionDetailTableBuilder.AppendLine("<td class=\"CellVide\"><img src=\"/medianamik/images/Icones/Ico_Fleche.png\" /></td>");
                            revisionDetailTableBuilder.AppendFormat(fieldNameColumn);
                            revisionDetailTableBuilder.AppendFormat("<td>{0}</td>\n",
                                FormatProperty(propertyPair, PropertyVersion.Current));
                            revisionDetailTableBuilder.AppendLine("</tr>");
                        }

                    }
                }

                revisionDetailTableBuilder.AppendLine("</table>");
            }
            else
            {
                saveButton.Enabled = false;
                saveButton.CssClass = "Action BtRevision-Inactif";
                revisionDetailTableBuilder.AppendLine("<p>" +
                    Translator.Translate("Medianamik_ContentManagement", "NoModification") + "</p>");
            }

            return revisionDetailTableBuilder.ToString();
        }

        private string FormatProperty(PropertyPair propertyPair, PropertyVersion version)
        {
            string result;

            if (propertyPair.IsUrl)
            {
                var value = version == PropertyVersion.Current ?
                propertyPair.CurrentValue : propertyPair.PreviousValue;

                result = GetUrlList(UrlHelper.GetUrlsFromXml(value, propertyPair.Culture));
            }
            else if (propertyPair.CouldBeHmtl) //HTML
            {
                var revision = version == PropertyVersion.Current ?
                propertyPair.CurrentRevision : propertyPair.PreviousRevision;

                string cssFilePath;
                if (CurrentNode.WebSite != null && !String.IsNullOrEmpty(CurrentNode.WebSite.CSSFilePath))
                    cssFilePath = CurrentNode.WebSite.CSSFilePath;
                else
                    cssFilePath = Config.DefaultEditorCSSFilePath;

                var url = "template.tpl".AddParam("css", cssFilePath).AddParam("propertyid", propertyPair.PropertyId)
                    .AddParam("nodeid", propertyPair.NodeId).AddParam("culture", propertyPair.Culture.Name);

                if (revision.HasValue)
                    url = url.AddParam("revision", revision.Value.Ticks);

                result = String.Format("<iframe src=\"{0}\" frameborder=\"0\" scrolling=\"no\" height=\"75\" class=\"iFrame\"></iframe>\n<p><a href=\"javascript:void(radopen('{1}', 'PropertyPreviewWindow'));\">{2}</a></p>",
                              url + "&removemargin=true", url, Translator.Translate("Medianamik_ContentManagement", "ViewCompleteContent"));
            }
            else
            {
                result = version == PropertyVersion.Current ?
                            propertyPair.CurrentValue : propertyPair.PreviousValue;
            }

            return result == String.Empty ? "&nbsp;" : result;
        }

        private static string GetUrlList(IEnumerable<IMedianamikUrl> urls)
        {
            var count = urls.Count();

            if (count > 0)
            {
                var listBuilder = new StringBuilder();
                listBuilder.AppendLine("<ul>");
                urls.ForEach(url => listBuilder.AppendLine("<li>" + url.Path + "</li>\n"));
                listBuilder.AppendLine("</ul>");
                return listBuilder.ToString();
            }

            return "";
        }

        protected void LoadBreadCrumbs()
        {
            BreadCrumbs.Breadcrumbs = CurrentNode.Breadcrumbs;
            BreadCrumbs.DataBind();
        }


        private enum PropertyVersion
        {
            Current,
            Previous
        }

        class PropertyPair
        {
            public PropertyPair(NodeProperty currentProperty, NodeProperty previousProperty,
                CultureInfo culture)
            {
                _groupName = currentProperty.GroupName;
                _name = currentProperty.Name;
                _currentValue = currentProperty.GetStringValue(culture);
                _previousValue = previousProperty.GetStringValue(culture);
                _hasChanged = _currentValue != _previousValue;
                _position = currentProperty.Position;
                _translatedName = Translator.Translate("TypeManagement", currentProperty.NodeTypePropertyID + "_Label");
                _couldBeHmtl = currentProperty.NodeTypeProperty.DataType.SQLDataTypeName.IndexOf("char",
                    StringComparison.OrdinalIgnoreCase) > -1 &&
                    (CouldContainHtml(_previousValue) || CouldContainHtml(_currentValue));
                _propertyId = currentProperty.NodeTypePropertyID;
                _nodeId = currentProperty.Node.ID;
                _isUrl = currentProperty.IsUrl;
                _currentRevision = currentProperty.NewRevision;
                _previousRevision = previousProperty.NewRevision;
                _culture = culture;
            }

            public DateTime? CurrentRevision
            {
                get { return _currentRevision; }
            }

            public DateTime? PreviousRevision
            {
                get { return _previousRevision; }
            }

            public CultureInfo Culture
            {
                get { return _culture; }
            }
            CultureInfo _culture;

            public int Position
            {
                get { return _position; }
            }
            readonly int _position;

            public string GroupName
            {
                get { return _groupName; }
            }
            readonly string _groupName;

            public Guid? PropertyId
            {
                get { return _propertyId; }
            }
            readonly Guid? _propertyId;

            public Guid? NodeId
            {
                get { return _nodeId; }
            }
            readonly Guid? _nodeId;

            public string Name
            {
                get { return _name; }
            }
            readonly string _name;

            public string TranslatedName
            {
                get { return _translatedName; }
            }
            readonly string _translatedName;

            public string CurrentValue
            {
                get { return _currentValue; }
            }
            readonly string _currentValue;

            public string PreviousValue
            {
                get { return _previousValue; }
            }
            readonly string _previousValue;

            readonly bool _hasChanged;
            public bool hasChanged
            {
                get { return _hasChanged; }
            }

            readonly bool _couldBeHmtl;
            public bool CouldBeHmtl
            {
                get { return _couldBeHmtl; }
            }

            readonly bool _isUrl;
            private DateTime? _previousRevision;
            private DateTime? _currentRevision;

            public bool IsUrl
            {
                get { return _isUrl; }
            }

            private static bool CouldContainHtml(string content)
            {
                if (String.IsNullOrEmpty(content))
                    return false;

                return content.IndexOf('<') > -1;
            }
        }
    }
}